package com.jacky.iot.models;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class FluxQueryBuilder {
    private final String bucket;
    private String range = "-1h";
    private final List<String> tagFilters = new ArrayList<>();
    private final List<String> fieldFilters = new ArrayList<>();

    public FluxQueryBuilder(String bucket) {
        this.bucket = bucket;
    }

    public FluxQueryBuilder range(String range) {
        this.range = range;
        return this;
    }

    public FluxQueryBuilder addTagFilter(String tag, String value) {
        if (value != null && !value.isEmpty()) {
            tagFilters.add("r.%s == \"%s\"".formatted(tag, value));
        }
        return this;
    }

    public FluxQueryBuilder addTagFilter(Map<String, Object> tagMap) {
        if (tagMap != null && !tagMap.isEmpty()) {
            tagMap.forEach((key, val) -> {
                tagFilters.add("r[\"%s\"] == \"%s\"".formatted(key, val));
            });
        }
        return this;
    }

    public FluxQueryBuilder addFieldFilter(String... fields) {
        for (String field : fields) {
            fieldFilters.add("r[\"_field\"] == \"%s\"".formatted(field));
        }
        return this;
    }

    public FluxQueryBuilder addFieldFilter(List<String>  fields) {
        for (String field : fields) {
            fieldFilters.add("r[\"_field\"] == \"%s\"".formatted(field));
        }
        return this;
    }

    public String build(String measurement, List<String> rowKeys) {
        StringBuilder flux = new StringBuilder();
        flux.append("from(bucket: \"%s\")\n".formatted(bucket))
                .append("  |> range(start: %s)\n".formatted(range))
                .append("  |> filter(fn: (r) => r[\"_measurement\"] == \"%s\")\n".formatted(measurement));

        if (!tagFilters.isEmpty()) {
            flux.append("  |> filter(fn: (r) => %s)\n".formatted(String.join(" and ", tagFilters)));
        }

        if (!fieldFilters.isEmpty()) {
            flux.append("  |> filter(fn: (r) => %s)\n".formatted(String.join(" or ", fieldFilters)));
        }

        if (rowKeys != null && !rowKeys.isEmpty()) {
            String rowKeyStr = rowKeys.stream()
                    .map(k -> "\"%s\"".formatted(k))
                    .collect(Collectors.joining(", "));
            flux.append("  |> pivot(rowKey: [%s], columnKey: [\"_field\"], valueColumn: \"_value\")\n"
                    .formatted(rowKeyStr));
        }

        return flux.toString();
    }
}